package no.ntnu.idi.deid.decision.validators.findPhrase.helpers;

import no.ntnu.idi.deid.documentunits.Phrase;
import no.ntnu.idi.deid.documentunits.Sentence;

public class LevenshteinDistanceLetter {
	
	private LevenshteinDistanceLetter() {
		
	}
	
    private static int minimum(int a, int b, int c) {
        return Math.min(Math.min(a, b), c);
	}

    
    /**
     * 	Calulates the levenshtein distance between str1 and str2
     * @param str1
     * @param str2
     * @return	the levenstein distance
     */
	private static int computeLevenshteinDistance(CharSequence str1,
			CharSequence str2) {
		int[][] distance = new int[str1.length() + 1][str2.length() + 1];

		for (int i = 0; i <= str1.length(); i++)
			distance[i][0] = i;
		for (int j = 1; j <= str2.length(); j++)
			distance[0][j] = j;

		for (int i = 1; i <= str1.length(); i++)
			for (int j = 1; j <= str2.length(); j++)
				distance[i][j] = minimum(
						distance[i - 1][j] + 1,
						distance[i][j - 1] + 1,
						distance[i - 1][j - 1]
								+ ((str1.charAt(i - 1) == str2.charAt(j - 1)) ? 0
										: 1));

		return distance[str1.length()][str2.length()];
	}
	
	public static Phrase findPhrase(Sentence s, String phrase, int maximumLevensteinDistancePerWord) {
		String[] phraseArray = phrase.split(" ");
		Phrase returnPhrase = null;
		for(int i = 0; i < s.size(); i++) {	
			if(phraseArray != null) {
				if(computeLevenshteinDistance(phraseArray[0].toLowerCase(), s.get(i).getStripped().toLowerCase()) <= maximumLevensteinDistancePerWord){			
					returnPhrase = matchPhrase(s, i, phraseArray, maximumLevensteinDistancePerWord);
					}
				}
		}
		return returnPhrase;
	}
	
	private static Phrase matchPhrase(Sentence s, int index,String[] phraseArray, int maximumLevensteinDistancePerWord){
		boolean result = true;
		int increment = index;
		for(int i = 0; i < phraseArray.length; i++) {
			if(s.tokenExists(increment)) {
				if(!(computeLevenshteinDistance(phraseArray[i].toLowerCase(), s.get(increment).getStripped().toLowerCase()) <= maximumLevensteinDistancePerWord)) {
					result = false;
				}
			}
			else {
				result = false;
				break;
			}
			increment++;			
		}
		if(result) {
			Phrase returnPhrase = new Phrase();
			for(int i = index; i < index+phraseArray.length; i++) {
				returnPhrase.add(s.get(i));
			}
			return returnPhrase;
		}
		else {
			return null;
		}
	}

}
